#include <Windows.h>
#include <tchar.h>
#include "resource.h"

struct SKey {
	const TCHAR* szName;
	DWORD dwValue;
	bool  bExtend;
	DWORD dwID;
};

int CALLBACK DlgProc(HWND hDlg, UINT nMsg, WPARAM wParam, LPARAM lParam)
{	
	static SKey Keys[] = {
		
			{_T("Esc"), VK_ESCAPE, false, 1},	{_T("F1"), VK_F1, false, 2},		{_T("PSN"), VK_SNAPSHOT, false, 3}, 
			{_T("1"), '1', false, 4},			{_T("<x"), VK_BACK, false, 5},		{_T("Tab"), VK_TAB, false, 6},
		
			{_T("Q"), 'Q', false, 7},			{_T("Enter"), VK_RETURN, false, 8},{_T("CapsLock"), VK_CAPITAL, false, 9},
			{_T("Shift"), VK_SHIFT, false, 10}, {_T("Ctrl"), VK_CONTROL, false, 11}, {_T("Win"), VK_LWIN, true, 12}, 
		
			{_T("Space"), VK_SPACE, false, 13}, {_T("Insert"), VK_INSERT, true, 14}, {_T("PageUp"), VK_PRIOR, true, 15},
			{_T("<-"), VK_LEFT, true, 16},		{_T("HOME"), VK_HOME, true, 17}, {_T("PageUp"), VK_PRIOR, true, 18},
			
			{_T("NumLock"), VK_NUMLOCK, true, 19}, {_T("0"), VK_NUMPAD0, false, 20}, {_T("+"), VK_ADD, true, 21},
			{_T("ScrollLock"), VK_SCROLL, true, 22}, {_T("Break"), VK_CANCEL, true, 23}, {_T("Enter"), VK_RETURN, true, 24},
					
	};

	switch (nMsg)
	{
		case WM_INITDIALOG:
		{
			SetWindowText(hDlg, _T("Demo0105"));

			UINT nWidth		= GetSystemMetrics(SM_CXSCREEN);
			UINT nHeight	= GetSystemMetrics(SM_CYSCREEN);
			RECT rtClient;
			GetClientRect(hDlg, &rtClient);
			SetWindowPos(hDlg, NULL, (nWidth - (rtClient.right - rtClient.left)) / 2, (nHeight - (rtClient.bottom - rtClient.top)) / 2, 0, 0, SWP_NOSIZE);
			
			int x = 50; 
			int y = 80;
			for (int ii = 0; ii < _countof(Keys); ii++)
			{
				x += 90;
				CreateWindow(_T("Button"), Keys[ii].szName, WS_VISIBLE|WS_CHILD, x, y, 80, 30, hDlg, (HMENU)Keys[ii].dwID, NULL, 0);
				if (0 == ((ii + 1) % 6) )
				{
					y += 50;
					x = 50;
				}				
			}
			break;
		}
		case WM_KEYDOWN:
		{
			TCHAR szTmp[MAX_PATH];
			_stprintf(szTmp, _T("\n%c  0x%x"), wParam, lParam);
			OutputDebugString(szTmp);

			TCHAR szKeyName[MAX_PATH] = {0};
			GetKeyNameText(lParam, szKeyName, 128);
 			OutputDebugString(szKeyName);
			
			if (0 != _tcslen(szKeyName))
			{	
				SetDlgItemText(hDlg, IDC_EDIT1, szKeyName);
			}

			break;
		}
		case WM_CHAR:
		{
			break;
		}
		case WM_COMMAND:
		{
			DWORD dwID = LOWORD(wParam);
			
			if (1 <= dwID && 30 > dwID)
			{
				DWORD dwKey = Keys[dwID - 1].dwValue;
 				keybd_event(dwKey, MapVirtualKey(dwKey, 0), Keys[dwID - 1].bExtend ? KEYEVENTF_EXTENDEDKEY|0 : 0, NULL);
				keybd_event(dwKey, MapVirtualKey(dwKey, 0),  Keys[dwID - 1].bExtend ? KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP : KEYEVENTF_KEYUP, NULL);
			}
			
			break;
		}
		case WM_CLOSE:
		{
			PostQuitMessage(0);
			break;
		}
	}

	return 0;
}

BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
	if (NULL != hWnd)
	{
		ShowWindow(hWnd, SW_SHOW);
		
		MSG msg;
		while (GetMessage(&msg, NULL, NULL, NULL))
		{
			if (msg.message == WM_KEYDOWN || msg.message == WM_KEYUP || msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP )
			{
				SendMessage(hWnd, msg.message, msg.wParam, msg.lParam);
			}

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return TRUE;
}